package com.swhysc.information.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.QBean;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.swhysc.information.entity.InformationDataDirectoryEx;
import com.swhysc.information.entity.InformationDataTableEx;
import com.swhysc.information.entity.QInformationDataDirectoryEx;
import com.swhysc.information.entity.QInformationDataTableEx;
import com.swhysc.information.repository.InformationDataDirExRepository;
import com.swhysc.information.repository.InformationDataTableExRepository;
import com.swhysc.information.service.IInformationDataDirExService;
import com.swhysc.information.vo.InformationDataDirectoryExTree;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author zmq
 * @Date 2022/10/13 18:13
 * @Description
 */
@Service
@Slf4j
public class InformationDataDirExServiceImpl implements IInformationDataDirExService {

    @Autowired
    private InformationDataDirExRepository repository;


    @Autowired
    private JPAQueryFactory jpaQueryFactory;
    @Autowired
    private InformationDataTableExRepository tableRepository;
    @Autowired
    private InformationDataTableExRepository informationDataTableRepository;

    @Value("${image.url}")
    private String imageUrl;


    @Override
    public Boolean create(InformationDataDirectoryEx informationDataDirectory) {
        Assert.isTrue(StringUtils.isNotBlank(informationDataDirectory.getCode()), "名称不能为空");
        Assert.isTrue(StringUtils.isNotBlank(informationDataDirectory.getCode()), "编码不能为空");
        //判断名称是否重复 名称需要和父id联合判断
        Assert.isTrue(!nameExist(informationDataDirectory.getParentId(), informationDataDirectory.getName(), informationDataDirectory.getId()), "名称重复");
        //判断编码是否重复 编码全局唯一
        Assert.isTrue(!codeExist(informationDataDirectory.getCode()), "编码重复");
        //默认不给parentId时，默认给-1
        if (StringUtils.isBlank(informationDataDirectory.getParentId())) {
            informationDataDirectory.setParentId("-1");
        }
        informationDataDirectory.setLevelCode(getdLevelCode(informationDataDirectory.getParentId()));
        informationDataDirectory.setCreateTime(new Date());
        informationDataDirectory.setUpdateTime(new Date());
        //informationDataDirectory.setCreateUser(UserSessionUtil.getEmpId());
        //informationDataDirectory.setUpdateUser(UserSessionUtil.getEmpId());
        return repository.save(informationDataDirectory) != null;
    }

    //根据父节点获取levelCode
    private String getdLevelCode(String parentId) {
        return getMaxChilren(parentId);
    }

    //获取最大节点
    private String getMaxChilren(String id) {
        QInformationDataDirectoryEx qInformationDataDirectory = QInformationDataDirectoryEx.informationDataDirectoryEx;
        String maxChild = repository.getMaxChilren(id);
        if (StringUtils.isNotBlank(maxChild)) {
            String temp = maxChild.substring(maxChild.length() - 6);
            String tempChild = parseData(Integer.parseInt(temp));
            String result = maxChild.substring(0, maxChild.length() - 6).trim()
                    + tempChild.trim();
            return result.trim();
        } else {
            String dlevelCode = jpaQueryFactory.select(qInformationDataDirectory.levelCode).from(qInformationDataDirectory).where(qInformationDataDirectory.id.eq(id)).fetchFirst();
            if (null == dlevelCode) {
                dlevelCode = "";
            }
            return dlevelCode + "000001";
        }
    }

    //格式化levelcode+1处理
    private static String parseData(int data) {
        data += 1;
        StringBuilder sb = new StringBuilder();
        int temp = data / 100000;
        sb.append(temp);
        temp = data / 10000 - (data / 100000) * 10;
        sb.append(temp);
        temp = data / 1000 - (data / 10000) * 10;
        sb.append(temp);
        temp = data / 100 - (data / 1000) * 10;
        sb.append(temp);
        temp = data / 10 - (data / 100) * 10;
        sb.append(temp);
        temp = data - (int) (data / 10) * 10;
        sb.append(temp);
        return sb.toString();
    }

    //用来判断名称是否重复
    private Boolean nameExist(String parentId, String name, String id) {
        QInformationDataDirectoryEx qInformationDataDirectory = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = qInformationDataDirectory.name.eq(name);
        if (StringUtils.isNotBlank(parentId)) {
            predicate = ExpressionUtils.and(predicate, qInformationDataDirectory.parentId.eq(parentId));
        }
        if (StrUtil.isNotBlank(id)) {
            predicate = ExpressionUtils.and(predicate, qInformationDataDirectory.id.ne(id));
        }
        List<InformationDataDirectoryEx> informationDataDirectories = jpaQueryFactory.selectFrom(qInformationDataDirectory).where(predicate).fetch();
        return informationDataDirectories.size() > 0;
    }

    //用来判断编码是否重复
    private Boolean codeExist(String code) {
        QInformationDataDirectoryEx qInformationDataDirectory = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = qInformationDataDirectory.code.eq(code);
        List<InformationDataDirectoryEx> informationDataDirectories = jpaQueryFactory.selectFrom(qInformationDataDirectory).where(predicate).fetch();
        return informationDataDirectories.size() > 0;
    }


    /**
     * 目录树列表接口
     *
     * @param type 类型 1 数据源 2 目录
     * @param name 目录名称
     * @param code 目录编码
     * @param id   id
     * @param page 页数
     * @param rows 行数
     * @return
     */
    @Override
    public List<InformationDataDirectoryEx> list(Integer type, String name, String code, String id, Integer page, Integer rows) {
        Assert.isTrue(null != type, "层级类型不能为空");
        Pageable pageable = PageRequest.of(page - 1, rows);
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        //拼接sql条件
        Predicate predicate = builderPredicate(type, name, code, id, qInfoDir);
        return jpaQueryFactory
                .select(buildQueryBean(qInfoDir))
                .from(qInfoDir)
                .where(predicate)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .orderBy(qInfoDir.sort.asc())
                .fetch().stream().map(item -> {
                    item.setImageUrl("/dasp/image/" + item.getImageUrl());
                    return item;
                }).collect(Collectors.toList());
    }

    private QBean<InformationDataDirectoryEx> buildQueryBean(QInformationDataDirectoryEx qInfoDir) {
        return Projections.bean(InformationDataDirectoryEx.class,
                qInfoDir.id,
                qInfoDir.name,
                qInfoDir.code,
                qInfoDir.describle,
                qInfoDir.sort,
                qInfoDir.level,
                qInfoDir.levelCode,
                qInfoDir.parentId,
                qInfoDir.isLeaf,
                qInfoDir.createTime,
                qInfoDir.updateTime,
                qInfoDir.type,
                qInfoDir.imageUrl
        );
    }

    /**
     * 资讯目录列表条数
     *
     * @param type 类型
     * @param name 名称
     * @param code 编码
     * @param pid  父id
     * @return int
     */
    @Override
    public int count(Integer type, String name, String code, String pid) {
        Assert.isTrue(null != type, "层级类型不能为空");
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = builderPredicate(type, name, code, pid, qInfoDir);
        return (int) jpaQueryFactory
                .selectFrom(qInfoDir)
                .where(predicate)
                .fetchCount();
    }


    /**
     * 资讯目录批量删除 删除-》有关联表信息的话不能删除   有下级节点的话不能删除
     *
     * @param idsList id集合
     * @param type    类型
     * @return int
     */
    @Override
    public Map deleteBatch(List<String> idsList, Integer type) {
        Map<String, Object> map = new HashMap<>();
        Assert.isTrue(null != type, "层级类型不能为空");
        Assert.isTrue(CollUtil.isNotEmpty(idsList), "id集合不能为空");
        List<String> deletedIds = new ArrayList<>();
        idsList.stream().forEach(id -> {
            //资讯目录
            if (2 == type) {
                int dirIdCount = tableRepository.findByDirId(id).size();
                //没有关联的表信息 和 没有子节点的可以删除
                int childerCount = checkHasChildren(id);
                if (0 == dirIdCount && 0 == childerCount) {
                    deletedIds.add(id);
                }
            }
            if (1 == type) {
                int dataSourceIdCount = tableRepository.findByDataSourceId(id).size();
                if (0 == dataSourceIdCount && 0 == checkHasChildren(id)) {
                    deletedIds.add(id);
                }
            }
        });
        log.info("【满足批量删除的有 {} 个】", deletedIds.size());
        Integer integer = null;
        try {
            integer = repository.deleteAllByIdIn(deletedIds);
            map.put("flag", true);
            map.put("message", "删除成功,删除" + integer + "条");
            return map;
        } catch (Exception e) {
            map.put("flag", false);
            map.put("message", "删除失败");
            e.printStackTrace();
            return map;
        }
    }

    /**
     * 校验是否有子节点数据
     *
     * @param id id
     * @return int 个数
     */
    private int checkHasChildren(String id) {
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        return (int) jpaQueryFactory.select(qInfoDir.id).from(qInfoDir)
                .where(qInfoDir.parentId.eq(id))
                .fetchCount();
    }

    /**
     * 获取树形结构数据
     *
     * @param id   id
     * @param name 名称
     * @return List
     */
    @Override
    public List<InformationDataDirectoryExTree> getTreeById(String id, String name) {
        //根据类型获取全部数据
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = qInfoDir.isNotNull().or(qInfoDir.isNull());
        if (StrUtil.isNotBlank(id)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.parentId.eq(id));
        }
        if (StrUtil.isNotBlank(name)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.name.eq(name));
        }
        /*List<InformationDataDirectoryEx> list = jpaQueryFactory.selectFrom(qInfoDir).where(predicate)
                .orderBy(qInfoDir.level.asc(),qInfoDir.sort.asc(),qInfoDir.updateTime.desc(),qInfoDir.name.asc())
                .fetch();*/
        QInformationDataTableEx qInformationDataTable = QInformationDataTableEx.informationDataTableEx;
        List<InformationDataDirectoryEx> collect = jpaQueryFactory.select(qInfoDir, qInformationDataTable.id)
                .from(qInfoDir)
                .leftJoin(qInformationDataTable)
                .on(qInfoDir.id.eq(qInformationDataTable.dirId))
                .where(predicate)
                .orderBy(qInfoDir.level.asc(), qInfoDir.sort.asc(), qInfoDir.updateTime.desc(), qInfoDir.name.asc())
                .fetch().stream().map(item -> {
                    InformationDataDirectoryEx informationDataDirectory = new InformationDataDirectoryEx();
                    BeanUtils.copyProperties(item.get(qInfoDir), informationDataDirectory);
                    if (StringUtils.isBlank(item.get(qInformationDataTable.id))) {
                        informationDataDirectory.setIsContsTable("0");
                    } else {
                        informationDataDirectory.setIsContsTable("1");
                    }
                    return informationDataDirectory;
                }).collect(Collectors.toList());
        LinkedHashSet<InformationDataDirectoryEx> informationDataDirectories = new LinkedHashSet<>(collect);
        List<InformationDataDirectoryEx> list = new ArrayList<>(informationDataDirectories);
        log.info("【获取树形结构数据 {}条】", list.size());
        List<InformationDataDirectoryExTree> trees = new ArrayList<>(list.size());
        if (CollUtil.isEmpty(list)) {
            return trees;
        }
        list.stream().forEach(info -> {
            InformationDataDirectoryExTree tree = new InformationDataDirectoryExTree();
            BeanUtils.copyProperties(info, tree);
            trees.add(tree);
        });
        id = StringUtils.defaultIfBlank(id, "-1");
        return listConvertTree(id, trees);
    }

    /**
     * list转tree结构
     *
     * @param zoneList list集合
     * @return List
     */
    public List<InformationDataDirectoryExTree> listConvertTree(String id, List<InformationDataDirectoryExTree> zoneList) {
        Map<String, List<InformationDataDirectoryExTree>> zoneByParentIdMap = zoneList.stream().collect(Collectors.groupingBy(InformationDataDirectoryExTree::getParentId));
        zoneList.forEach(zone -> zone.setChildren(zoneByParentIdMap.get(zone.getId())));
        return zoneList.stream().filter(v -> id.equals(v.getParentId())).collect(Collectors.toList());
    }

    /**
     * 修改
     *
     * @param infoDataDirectory 数据源、目录实体
     * @return InformationDataDirectoryEx
     */
    @Override
    public Boolean update(InformationDataDirectoryEx infoDataDirectory) {
        Assert.isTrue(StringUtils.isNotBlank(infoDataDirectory.getName()), "名称不能为空");
        Assert.isTrue(StringUtils.isNotBlank(infoDataDirectory.getCode()), "编码不能为空");
        Assert.isTrue(null != infoDataDirectory.getType(), "类型不能为空");
        //判断名称是否重复
        Assert.isTrue(!nameExist(infoDataDirectory.getParentId(), infoDataDirectory.getName(), infoDataDirectory.getId()), "名称重复");
        //判断编码是否重复
        Assert.isTrue(!checkCodeExist(infoDataDirectory.getId(), infoDataDirectory.getCode()), "编码重复");
        //判断该节点有子节点数据不能修改为叶子节点
        boolean flag = false;
        if (checkHasChildren(infoDataDirectory.getId()) > 0 && ObjectUtil.equal("1", infoDataDirectory.getIsLeaf())) {
            flag = true;
        }
        Assert.isTrue(!flag, "存在子节点不能修改为叶子节点");
        //判断该节点有关联信息，不能修改为非叶子节点
        checkHasRelationInfo(infoDataDirectory.getId(), infoDataDirectory.getType(), infoDataDirectory.getIsLeaf());

        //对数据源进行修改
        if (infoDataDirectory.getType() == 1) {
            //infoDataDirectory.setUpdateUser(UserSessionUtil.getEmpId());
            infoDataDirectory.setUpdateTime(new Date());
            return repository.save(infoDataDirectory) != null;
        }
        //对目录进行修改限制
        if (infoDataDirectory.getType() == 2) {
            //infoDataDirectory.setUpdateUser(UserSessionUtil.getEmpId());
            infoDataDirectory.setUpdateTime(new Date());
            return repository.save(infoDataDirectory) != null;
        }
        return null;
    }

    /**
     * 修改校验编码code唯一，排除本身的id的code
     *
     * @param id   id
     * @param code 编码
     * @return boolean
     */
    private boolean checkCodeExist(String id, String code) {
        QInformationDataDirectoryEx qInformationDataDirectory = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = qInformationDataDirectory.code.eq(code).and(qInformationDataDirectory.id.ne(id));
        List<InformationDataDirectoryEx> informationDataDirectories = jpaQueryFactory.selectFrom(qInformationDataDirectory).where(predicate).fetch();
        return informationDataDirectories.size() > 0;
    }

    /**
     * 根据id获取目录数据
     *
     * @param id   主键id
     * @param type 类型
     * @return
     */
    @Override
    public InformationDataDirectoryEx view(String id, Integer type) {
        Assert.isTrue(null != type, "type是必填项");
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        InformationDataDirectoryEx directory = jpaQueryFactory.select(qInfoDir).from(qInfoDir)
                .where(qInfoDir.id.eq(id).and(qInfoDir.type.eq(type))).fetchOne();
        return directory != null ? directory : null;
    }


    /**
     * 判断该节点有关联信息，不能修改为非叶子节点
     *
     * @param id     id
     * @param type   类型
     * @param isLeaf 是否叶子节点
     */
    private void checkHasRelationInfo(String id, Integer type, String isLeaf) {
        if (2 == type) {
            int dataSourceCount = tableRepository.findByDirId(id).size();
            Assert.isTrue(!(dataSourceCount > 0 && ObjectUtil.equal("0", isLeaf)), "存在关联表信息,不能修改为非叶子节点");
        }
    }


    /**
     * 组装查询条件
     *
     * @param type     类型
     * @param name     名称
     * @param code     编码
     * @param id       id
     * @param qInfoDir 实体
     * @return Predicate
     */
    private Predicate builderPredicate(Integer type, String name, String code, String id, QInformationDataDirectoryEx qInfoDir) {
        //初始化组装条件(类似where 1=1)
        Predicate predicate = qInfoDir.isNotNull().or(qInfoDir.isNull());
        predicate = ExpressionUtils.and(predicate, qInfoDir.type.eq(type));
        if (StringUtils.isNotEmpty(name)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.name.
                    like("%" + name.trim() + "%"));
        }
        if (StringUtils.isNotEmpty(code)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.code.
                    like("%" + code.trim() + "%"));
        }
        //id匹配parentId
        if (StrUtil.isNotBlank(id)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.parentId.eq(id));
        }
        return predicate;
    }

    @Override
    public Boolean format() {
        List<InformationDataDirectoryEx> informationDataDirectoryList = new ArrayList<>();
        deal("-1", "", informationDataDirectoryList);
        return repository.saveAll(informationDataDirectoryList).size() > 0;
    }

    //格式化levelCode
    public void deal(String id, String dlevelcode, List<InformationDataDirectoryEx> list) {
        List<InformationDataDirectoryEx> dataDirectories = repository.findByParentId(id);
        int index = 1;
        for (InformationDataDirectoryEx item : dataDirectories) {
            String currentId = item.getId();
            String currentDlc = item.getLevelCode();
            String newDlcSuffix = "000000".substring(String.valueOf(index)
                    .length());
            String newLevelCode = dlevelcode + newDlcSuffix + index;
            if (newLevelCode.length() % 6 != 0) {
                log.info("数据错误，ID" + currentId + "\tDLC" +
                        currentDlc + "\tNEWDLC" + newLevelCode);
            }
            item.setLevelCode(newLevelCode);
            list.add(item);
            index++;
            deal(currentId, newLevelCode, list);
        }
    }

    @Override
    public List<InformationDataDirectoryEx> allList(Integer type, String name, String code, String id, Integer page, Integer rows) {
        Assert.isTrue(null != type, "层级类型不能为空");
        Assert.isTrue(StringUtils.isNotBlank(id), "层级id不能为空");
        //获取当前目录的层级编码
        Optional<InformationDataDirectoryEx> optional = repository.findById(id);
        InformationDataDirectoryEx informationDataDirectory = optional.get();
        String levelCode = informationDataDirectory.getLevelCode();
        Pageable pageable = PageRequest.of(page - 1, rows);
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        //拼接sql条件
        Predicate predicate = builderPredicate1(type, name, code, levelCode, qInfoDir);
        List<InformationDataDirectoryEx> list = jpaQueryFactory
                .select(buildQueryBean(qInfoDir))
                .from(qInfoDir)
                .where(predicate)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .orderBy(qInfoDir.level.asc(), qInfoDir.sort.asc(), qInfoDir.updateTime.desc(), qInfoDir.name.asc())
                .fetch().stream().map(item -> {
                    item.setImageUrl("/dasp/image/" + item.getImageUrl());
                    return item;
                }).collect(Collectors.toList());
        return list;
    }

    @Override
    public int allCount(Integer type, String name, String code, String id) {
        Assert.isTrue(null != type, "层级类型不能为空");
        Assert.isTrue(StringUtils.isNotBlank(id), "层级id不能为空");
        //获取当前目录的层级编码
        Optional<InformationDataDirectoryEx> optional = repository.findById(id);
        InformationDataDirectoryEx informationDataDirectory = optional.get();
        String levelCode = informationDataDirectory.getLevelCode();
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = builderPredicate1(type, name, code, levelCode, qInfoDir);
        return (int) jpaQueryFactory
                .selectFrom(qInfoDir)
                .where(predicate)
                .fetchCount();
    }

    /**
     * 组装查询条件
     *
     * @param type     类型
     * @param name     名称
     * @param code     编码
     * @param qInfoDir 实体
     * @return Predicate
     */
    private Predicate builderPredicate1(Integer type, String name, String code, String levelCode, QInformationDataDirectoryEx qInfoDir) {
        //初始化组装条件(类似where 1=1)
        Predicate predicate = qInfoDir.isNotNull().or(qInfoDir.isNull());
        predicate = ExpressionUtils.and(predicate, qInfoDir.type.eq(type));
        if (StringUtils.isNotEmpty(name)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.name.
                    like("%" + name.trim() + "%"));
        }
        if (StringUtils.isNotEmpty(code)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.code.
                    like("%" + code.trim() + "%"));
        }
        //id匹配parentId
        if (StrUtil.isNotBlank(levelCode)) {
            predicate = ExpressionUtils.and(predicate, qInfoDir.levelCode.startsWith(levelCode));
            predicate = ExpressionUtils.and(predicate, qInfoDir.levelCode.notEqualsIgnoreCase(levelCode));
        }
        return predicate;
    }

    @Override
    public List<InformationDataDirectoryExTree> getAllTree(String id) {
        //判读是否传入id,无查询全部,有查询当前节点下的所有节点
        List<InformationDataDirectoryEx> lists;
        if (StringUtils.isNotBlank(id)) {
            lists = getDirList(id);
        } else {
            lists = repository.findAll();
        }
        //封装成tree结构
        List<InformationDataDirectoryExTree> trees = new ArrayList<>();
        for (InformationDataDirectoryEx list : lists) {
            InformationDataDirectoryExTree informationDataDirectoryTree = new InformationDataDirectoryExTree();
            BeanUtils.copyProperties(list, informationDataDirectoryTree);
            trees.add(informationDataDirectoryTree);
        }
        String pid = StringUtils.defaultIfBlank(id, "-1");
        //递归组装树结构
        List<InformationDataDirectoryExTree> tree = getTree(trees, pid);
        return tree;
    }


    public List<InformationDataDirectoryExTree> getTree(List<InformationDataDirectoryExTree> trees, String pid) {
        List<InformationDataDirectoryExTree> child = new ArrayList<>();
        for (InformationDataDirectoryExTree tree : trees) {
            String id = tree.getId();
            String parentId = tree.getParentId();
            //是当前节点的子节点，递归组
            if (parentId.equals(pid)) {
                List<InformationDataDirectoryExTree> tree1 = getTree(trees, id);
                tree.setChildren(tree1);
                child.add(tree);
            }
        }
        return child;
    }

    public List<InformationDataDirectoryEx> getDirList(String dirId) {
        //根据id获取到levelcode，模糊查询levelcode的全部数据 (isleaf=1 )，最终获取最后节点的id集合
        InformationDataDirectoryEx dirRepositoryOne = repository.getOne(dirId);
        if (ObjectUtil.isEmpty(dirRepositoryOne)) {
            return Lists.newArrayList();
        }
        String levelCode = dirRepositoryOne.getLevelCode();
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        Predicate predicate = qInfoDir.isNotNull().or(qInfoDir.isNull());
        //叶子节点 + 目录类型
        predicate = ExpressionUtils.and(predicate, qInfoDir.type.eq(2));
        predicate = ExpressionUtils.and(predicate, qInfoDir.levelCode.startsWith(levelCode.trim()));

        List<InformationDataDirectoryEx> directoryList = jpaQueryFactory.selectFrom(qInfoDir).where(predicate).fetch();
        return directoryList;
    }

    @Override
    public JSONObject getTableTree(String tableId) {
        JSONArray jsonArray = new JSONArray();
        JSONObject ject = new JSONObject();
        List<JSONObject> informationDataDirectoryList = new ArrayList<>();
        InformationDataTableEx informationDataTable = informationDataTableRepository.findById(tableId).orElse(null);
        Assert.isTrue(null != informationDataTable, "表ID不能为空");
        String dirId = informationDataTable.getDirId();//目录id
        //获取当前目录下所有的表
        List<InformationDataTableEx> dataTables = tableRepository.findByDirIdOrderBySortAscUpdateTimeDescEnNameAsc(dirId);//获取目录下所有的表
        //获取当前目录信息
        InformationDataDirectoryEx informationDataDirectory = repository.findById(dirId).orElse(null);
        Assert.isTrue(null != informationDataDirectory, "表关联目录不存在");
        //添加本身，添加父级目录
        JSONObject tableJson = new JSONObject();
        tableJson.put("id", informationDataTable.getId());
        tableJson.put("name", informationDataTable.getChName() == null || "".equals(informationDataTable.getChName()) ? informationDataTable.getEnName() : informationDataTable.getChName());
        informationDataDirectoryList.add(tableJson);
        JSONObject jsonObject = JSONObject.parseObject(JSONUtil.toJsonStr(informationDataDirectory));
        informationDataDirectoryList.add(jsonObject);
        jsonObject.put("children", dataTables);
        if (!informationDataDirectory.getLevel().equals("1")) {
            jsonObject = getParent(jsonObject, informationDataDirectory.getParentId(), informationDataDirectoryList);
        }
        String dataSourceId = informationDataTable.getDataSourceId();//数据源id
        //获取一级目录
        List<InformationDataDirectoryEx> directoryList = repository.findByParentIdOrderByLevelAscSortAscUpdateTimeDescNameAsc(dataSourceId);
        //进行判断 替换
        for (InformationDataDirectoryEx directory : directoryList) {
            JSONObject object = JSONObject.parseObject(JSONUtil.toJsonStr(directory));
            if (directory.getId().equals(jsonObject.getString("id"))) {
                jsonArray.add(jsonObject);
            } else {
                jsonArray.add(object);
            }
        }
        Collections.reverse(informationDataDirectoryList);
        ject.put("list", jsonArray);
        ject.put("arr", informationDataDirectoryList);
        return ject;
    }

    //获取上级树结构，并返回jsonobject
    private JSONObject getParent(JSONObject jsonObject, String dirId, List<JSONObject> informationDirctoryList) {
        InformationDataDirectoryEx informationDataDirectory = repository.findById(dirId).orElse(null);
        if (informationDataDirectory != null) {
            informationDirctoryList.add(JSONObject.parseObject(JSONUtil.toJsonStr(informationDataDirectory)));
            JSONObject job = JSONObject.parseObject(JSONUtil.toJsonStr(informationDataDirectory));
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(jsonObject);
            job.put("children", jsonArray);
            if (informationDataDirectory.getLevel().equals("1")) {
                return job;
            } else {
                return getParent(job, informationDataDirectory.getParentId(), informationDirctoryList);
            }
        } else {
            return jsonObject;
        }
    }

    @Override
    public Map moveDir(String dirId, String tagDirId, String moveType) {
        Map<String, Object> map = new HashMap<>();
        map.put("flag", false);
        InformationDataDirectoryEx informationDataDirectory = repository.getOne(dirId);
        InformationDataDirectoryEx tagInformationDataDir = repository.getOne(tagDirId);
        //校验是否存在
        if (informationDataDirectory == null) {
            map.put("message", "要移动的目录不存在！");
            return map;
        }
        if (tagInformationDataDir == null) {
            map.put("message", "要移动到的目标目录不存在！");
            return map;
        }
        if (!informationDataDirectory.getParentId().equals(tagInformationDataDir.getParentId()) || (informationDataDirectory.getParentId().equals(tagInformationDataDir.getParentId()) && "inner".equals(moveType))) {
            map.put("message", "不允许移动到其他目录！");
            return map;
        }
        //不允许移动到其他目录
        //Assert.isTrue(!(!informationDataDirectory.getParentId().equals(tagInformationDataDir.getParentId()) || (informationDataDirectory.getParentId().equals(tagInformationDataDir.getParentId()) && "inner".equals(moveType))),"不允许移动到其他目录！");
        QInformationDataDirectoryEx qInformationDataDirectory = QInformationDataDirectoryEx.informationDataDirectoryEx;
        //获取所有兄弟节点
        List<InformationDataDirectoryEx> brotherList = jpaQueryFactory.select(qInformationDataDirectory)
                .from(qInformationDataDirectory)
                .where(qInformationDataDirectory.parentId.eq(informationDataDirectory.getParentId()))
                .orderBy(qInformationDataDirectory.level.asc(), qInformationDataDirectory.sort.asc(), qInformationDataDirectory.updateTime.desc(), qInformationDataDirectory.name.asc())
                .fetch();
        int tag = 0;
        for (int i = 0; i < brotherList.size(); i++) {
            //找到 目标位置
            String id = brotherList.get(i).getId();
            if (id.equals(tagDirId)) {
                tag = i;
            }
        }
        //判断位置是否是底部位置
        boolean flag = false;
        if ("after".equals(moveType) && (tag + 1) == brotherList.size()) {
            flag = true;
        }
        ArrayList<InformationDataDirectoryEx> informationDataDirectories = new ArrayList<>();
        if (flag) {
            //获取前临的兄弟的排序号，加一
            InformationDataDirectoryEx beforBrother = brotherList.get(tag);
            informationDataDirectory.setSort(beforBrother.getSort() + 1);
            informationDataDirectories.add(informationDataDirectory);
        } else {
            //处理本身
            //获取前临的兄弟的排序号
            InformationDataDirectoryEx tagInforDir = brotherList.get(tag);
            int begin = 0;
            long sort = 0;
            if ("after".equals(moveType)) { //之后加1
                informationDataDirectory.setSort(tagInforDir.getSort() + 1);
                sort = tagInforDir.getSort() + 1;
                begin = tag + 1;

            } else if ("before".equals(moveType)) { //之前 直接替换兄弟的排序号
                informationDataDirectory.setSort(tagInforDir.getSort());
                sort = tagInforDir.getSort();
                begin = tag;
            }
            for (int i = begin; i < brotherList.size(); i++) {
                InformationDataDirectoryEx brother = brotherList.get(i);
                if (!brother.getId().equals(dirId)) {
                    sort += 1;
                    brother.setSort(sort);
                    informationDataDirectories.add(brother);
                }
            }
            informationDataDirectories.add(informationDataDirectory);
            //获取后临的兄弟的 排序号
        }
        try {
            repository.saveAll(informationDataDirectories);
            map.put("flag", true);
            map.put("message", "移动目录成功！");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("flag", false);
            map.put("message", "移动目录失败！");
        }
        return map;
    }

    @Override
    public JSONObject getTableTree2(String tableId) {
        JSONArray jsonArray = new JSONArray();
        JSONObject ject = new JSONObject();
        List<String> strings = new ArrayList<>();
        InformationDataTableEx informationDataTable = informationDataTableRepository.findById(tableId).orElse(null);
        Assert.isTrue(null != informationDataTable, "表ID不能为空");
        String dirId = informationDataTable.getDirId();//目录id
        //获取当前目录下所有的表
        List<InformationDataTableEx> dataTables = tableRepository.findByDirIdOrderBySortAscUpdateTimeDescEnNameAsc(dirId);//获取目录下所有的表
        //获取当前目录信息
        InformationDataDirectoryEx informationDataDirectory = repository.findById(dirId).orElse(null);
        Assert.isTrue(null != informationDataDirectory, "表关联目录不存在");
        informationDataDirectory.setIsContsTable("1");
        //添加表及目录id
        strings.add(tableId);
        strings.add(dirId);
        JSONObject jsonObject = JSONObject.parseObject(JSONUtil.toJsonStr(informationDataDirectory));
        jsonObject.put("children", dataTables);
        if (!informationDataDirectory.getLevel().equals("0")) {
            jsonObject = getParent2(jsonObject, informationDataDirectory.getParentId(), strings);
        }
        //获取数据源目录
        List<InformationDataDirectoryEx> directoryList = repository.findByLevelOrderByLevelAscSortAscUpdateTimeDescNameAsc("0");
        //进行判断 替换
        for (InformationDataDirectoryEx directory : directoryList) {
            JSONObject object = JSONObject.parseObject(JSONUtil.toJsonStr(directory));
            if (directory.getId().equals(jsonObject.getString("id"))) {
                jsonArray.add(jsonObject);
            } else {
                jsonArray.add(object);
            }
        }
        Collections.reverse(strings);
        ject.put("arr", strings);
        ject.put("list", jsonArray);
        return ject;
    }

    //获取上级树结构，并返回jsonobject
    private JSONObject getParent2(JSONObject jsonObject, String dirId, List<String> strings) {
        //InformationDataDirectoryEx informationDataDirectory = repository.findById(dirId).orElse(null);
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        QInformationDataTableEx qInformationDataTable = QInformationDataTableEx.informationDataTableEx;
        Tuple tuple = jpaQueryFactory.select(qInfoDir, qInformationDataTable.id)
                .from(qInfoDir)
                .leftJoin(qInformationDataTable)
                .on(qInfoDir.id.eq(qInformationDataTable.dirId))
                .where(qInfoDir.id.eq(dirId))
                .orderBy(qInfoDir.level.asc(), qInfoDir.sort.asc(), qInfoDir.updateTime.desc(), qInfoDir.name.asc())
                .fetchFirst();
        if (tuple != null) {
            InformationDataDirectoryEx informationDataDirectory = tuple.get(qInfoDir);
            if (StringUtils.isBlank(tuple.get(qInformationDataTable.id))) {
                informationDataDirectory.setIsContsTable("0");
            } else {
                informationDataDirectory.setIsContsTable("1");
            }
            if (informationDataDirectory != null) {
                strings.add(informationDataDirectory.getId());
                JSONObject job = JSONObject.parseObject(JSONUtil.toJsonStr(informationDataDirectory));
                JSONArray jsonArray = new JSONArray();
                jsonArray.add(jsonObject);
                job.put("children", jsonArray);
                if (informationDataDirectory.getLevel().equals("0")) {
                    return job;
                } else {
                    return getParent2(job, informationDataDirectory.getParentId(), strings);
                }
            } else {
                return jsonObject;
            }
        } else {
            return jsonObject;
        }
    }

    @Override
    public List<InformationDataDirectoryEx> getDataSource() {
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        List<InformationDataDirectoryEx> fetch = jpaQueryFactory.selectFrom(qInfoDir)
                .where(qInfoDir.type.eq(1))
                .orderBy(qInfoDir.sort.asc())
                .fetch().stream().map(item -> {
                    //获取图片路径
                    item.setImageUrl("/dasp/image/" + item.getImageUrl());
                    return item;
                }).collect(Collectors.toList());
        return fetch;
    }

    public List<String> getDataSourceId() {
        QInformationDataDirectoryEx qInfoDir = QInformationDataDirectoryEx.informationDataDirectoryEx;
        List<String> fetch = jpaQueryFactory.select(qInfoDir.id)
                .from(qInfoDir)
                .where(qInfoDir.type.eq(1))
                .orderBy(qInfoDir.sort.asc())
                .fetch();
        return fetch;
    }

    @Override
    public Object uploadImage(MultipartFile file) {
        Map<String, Object> result = new HashMap<>();
        String fileSavePath = imageUrl;
        if (null == file || file.getSize() <= 0) {
            result.put("flag", false);
            result.put("msg", "请选择上传文件！");
            return result;
        }
        String originalName = file.getOriginalFilename();
        if (!originalName.toLowerCase().endsWith(".jpg")
                && !originalName.toLowerCase().endsWith(".jpeg")
                && !originalName.toLowerCase().endsWith(".png")
                && !originalName.toLowerCase().endsWith(".gif")) {
            result.put("flag", false);
            result.put("msg", "只能上传图片格式！");
            return result;
        }
        long maxSize = 2 * 1024 * 1024;
        long size = file.getSize();
        if (size > maxSize) {
            result.put("flag", false);
            result.put("msg", "图片最大只能为2M！");
            return result;
        }
        //文件名
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String picNewName = fileName + originalName.substring(originalName.lastIndexOf("."));
        String imgRealPath = fileSavePath + picNewName;
        try {
            File f = new File(fileSavePath);
            if (!f.exists()) {
                f.mkdirs();
            }
            //保存图片-将file对象装入image文件中
            File imageFile = new File(imgRealPath);
            file.transferTo(imageFile);
        } catch (Exception e) {
            result.put("flag", false);
            result.put("msg", "图片保存异常");
            return result;
        }
        result.put("flag", true);
        result.put("msg", "图片保存成功！");
        result.put("name", picNewName);
        return result;
    }
}
